package com.cocotingo.snail.dispatcher;

import java.util.LinkedList;
import java.util.List;

public class DispatchQueue {
	
	private final int count;
	private int current;
	private final List<Runnable> queue;
	
	public DispatchQueue() {
		this(1);
	}
	
	public DispatchQueue(final int count) {
		if (count <= 0)
			throw new IllegalArgumentException("DispatchQueue.count <= 0");
		this.count = count;
		current = 0;
		queue = new LinkedList<Runnable>();
	}
	
	public synchronized void execute(final Runnable target) {
		if (current < count) {
			Dispatcher.execute(new Runnable() {
				@Override
				public void run() {
					target.run();
					Runnable next = null;
					synchronized (DispatchQueue.this) {
						current--;
						if (queue.size() > 0) {
							next = queue.remove(0);
						}
					}
					if (next != null) execute(next);
				}
			});
			current++;
		} else {
			queue.add(target);
		}
	}
	
	public void executeAndWait(final Runnable target) {
		final Blocker blocker = new Blocker();
		execute(new Runnable() {
			@Override
			public void run() {
				target.run();
				blocker.unlock();
			}
		});
		try {
			blocker.lock();
		} catch (InterruptedException e) {
			throw new IllegalStateException("current thread was interrupted.", e);
		}
	}
	
}
